﻿package com.flashframeless.components.ui.lightBox {
	
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import com.hydrotik.utils.QueueLoader;
	import com.hydrotik.utils.QueueLoaderEvent;
	import flash.events.MouseEvent;
	
	import gs.TweenLite;
	import gs.TweenMax;
	import gs.easing.Quint;
	
	/**
	 * ...
	 * @author ...
	 */
	public class LightBox extends Sprite{
		
		private var _alvo			: Sprite;
		private var _alvoHandler	: Sprite;
		private var _bgAlvo			: Sprite;
		private var _backGround		: Sprite;
		private var _nextArrow		: Sprite;
		private var _prevArrow		: Sprite;
		private var _close			: Sprite;
		private var _loading		: MovieClip;
		private var _arrImages		: Array;
		private var i				: uint;
		private var _loader			: QueueLoader;
		private var _imageIndex		: uint		= 0;
		private var _activate		: Boolean;
		private var _originalImageW	: Number;
		private var _originalImageH	: Number;
		
		private const OPACITY		: Number 	= .95;
		private const BORDER_SIZE	: uint 		= 10;
		private const PADDING_SIZE	: uint 		= 10;
		
		public function LightBox() {
			
			instanciate();
			
		}
		
		private function instanciate():void {
			
			_bgAlvo			= bgAlvoMc;
			_close			= closeMc;
			_nextArrow		= nextArrowMc;
			_prevArrow		= prevArrowMc;
			_backGround 	= bgMc;
			_loading		= loadingMc;
			_alvoHandler 	= alvoMc;
			
			setupInteractions();
			
		}
		
		private function setupInteractions():void {
			
			this.visible 	= false;
			this.alpha		= 0;
			
			_backGround.addEventListener( MouseEvent.CLICK, close );			
			
			//animate( 'OUT' );			
			
			//openImage( 'http://localhost:83/projetos/$_UrbanJobs/0005_Urban.arts/site2009/final/_content/img/sinisc_equilibrista.jpg' );
			
		}
		
		private function animate( type:String ):void {
			
			switch( type ) {
				
				case 'IN':
					
					_backGround.width 	= _backGround.height 	= _backGround.alpha = 0;
					
					_bgAlvo.width 		= _bgAlvo.height 		= _loading.width + BORDER_SIZE;
					_bgAlvo.alpha 		= _alvo.alpha 			= _loading.alpha = 0;
					
					_nextArrow.alpha 	= _prevArrow.alpha 		= _close.alpha = 0;
					
					this.visible 	= true;
					this.alpha		= 1;
					
					//Animate Main BackGround
					TweenLite.to( _backGround, .5, { alpha:OPACITY, width:stage.stageWidth, height:stage.stageHeight, ease:Quint.easeInOut, onComplete:function() {
						
						//Set objects positions
						_bgAlvo.x = stage.stageWidth / 2 - _bgAlvo.width / 2;
						_bgAlvo.y = stage.stageHeight / 2 - _bgAlvo.height / 2;
						
						_loading.x = _bgAlvo.x + _bgAlvo.width / 2;
						_loading.y = _bgAlvo.y + _bgAlvo.height / 2;
						
						//Animate Alvo/Loading BackGround
						TweenLite.from( _bgAlvo, 	.5, { width:0, height:0 } );
						TweenLite.to( _bgAlvo, 		.5, { alpha:1 } );
						
						//Animate Loading
						TweenLite.to( _loading, 	.5, { alpha:1, delay:.5 } );
						
					} } );
					
				break;
				
				case 'OUT':
					
					TweenLite.to( this, .5, { 
						
						ease:		Quint.easeOut,
						alpha:		0,
						visible:	false
						
					} );
					
				break;
				
			}
			
		}
		
		private function openImage( url:String ):void {
			
			activeListeners( false );
			
			TweenLite.to( _prevArrow, 	.3, { alpha:0 } );
			TweenLite.to( _nextArrow, 	.3, { alpha:0 } );
			TweenLite.to( _close, 		.3, { alpha:0, onComplete:function() {
				
				_prevArrow.visible = _nextArrow.visible = false;
				
			} } );
			
			if ( _alvo ) {
				
				_alvo.removeEventListener( MouseEvent.MOUSE_OVER, 	imageOver 	);
				_alvo.removeEventListener( MouseEvent.MOUSE_OUT, 	imageOut 	);
				_alvo.removeEventListener( MouseEvent.CLICK, 		close 		);
				removeChild( _alvo );
				
			}
			
			_alvo = new Sprite;	
			
			_alvo.addEventListener( MouseEvent.MOUSE_OVER, 			imageOver 	);
			_backGround.addEventListener( MouseEvent.MOUSE_OVER, 	imageOut 	);
			_alvo.addEventListener( MouseEvent.CLICK, 				close 		);
			addChild( _alvo );
			
			setChildIndex( _backGround,	0 );
			setChildIndex( _bgAlvo, 	1 );
			setChildIndex( _loading, 	2 );
			setChildIndex( _alvo, 		3 );
			
			if ( !this.visible ) {
				
				animate( 'IN' );
				
			}
			
			if ( _bgAlvo.width > _loading.width + BORDER_SIZE ) {
				
				TweenLite.to( _alvo, .5, { alpha:0, onComplete:function() {
					
					TweenLite.to( _bgAlvo, .5, { 
						
						width: 	_loading.width + BORDER_SIZE,
						height:	_loading.width + BORDER_SIZE,
						x:		stage.stageWidth / 2 - ( _loading.width + BORDER_SIZE ) / 2,
						y:		stage.stageHeight / 2 - ( _loading.width + BORDER_SIZE ) / 2
						
					} );
					
					TweenLite.to( _loading, .5, { 
						
						delay:	.5,
						alpha:	1
						
					} );
					
					_loader = new QueueLoader();
					
					_loader.addItem( url, _alvo, { title:'image' } );
					
					_loader.addEventListener( QueueLoaderEvent.ITEM_COMPLETE, itemComplete );
					_loader.addEventListener( QueueLoaderEvent.QUEUE_COMPLETE, queueComplete );
					
					_loader.execute();
					
				} } );
				
			} else {
				
				_loader = new QueueLoader();
				
				_loader.addItem( url, _alvo, { title:'image' } );
				
				_loader.addEventListener( QueueLoaderEvent.ITEM_COMPLETE, itemComplete );
				_loader.addEventListener( QueueLoaderEvent.QUEUE_COMPLETE, queueComplete );
				
				_loader.execute();
				
			}
				
		}
		
		public function reAlign():void {
			
			//Set objects positions
			_bgAlvo.x = stage.stageWidth / 2 - _bgAlvo.width / 2;
			_bgAlvo.y = stage.stageHeight / 2 - _bgAlvo.height / 2;
			
			_alvo.x = _bgAlvo.x + PADDING_SIZE / 2;
			_alvo.y = _bgAlvo.y + PADDING_SIZE / 2;
			
			_loading.x = _bgAlvo.x + _bgAlvo.width / 2;
			_loading.y = _bgAlvo.y + _bgAlvo.height / 2;
			
			_backGround.width = stage.stageWidth;
			_backGround.height = stage.stageHeight;
			
			alignButtons();
			
		}
		
		private function alignButtons():void {
			
			_nextArrow.x = Math.round( _bgAlvo.x + _bgAlvo.width - _nextArrow.width - BORDER_SIZE );
			_prevArrow.x = Math.round( _bgAlvo.x + _prevArrow.width + BORDER_SIZE );
			_nextArrow.y = Math.round( _bgAlvo.y + _bgAlvo.height/2 - _nextArrow.height/2 );
			_prevArrow.y = Math.round( _bgAlvo.y + _bgAlvo.height/2 + _nextArrow.height/2 );
			
			_close.y = Math.round( _bgAlvo.y + _bgAlvo.height / 2 - _close.height / 2 );
			_close.x = Math.round( _bgAlvo.x + _bgAlvo.width / 2 - _close.width / 2 );
			
		}
		
		private function nextImage( evt:MouseEvent ):void {
			
			_imageIndex++;
			openImage( _arrImages[_imageIndex].url );
			
		}
		
		private function prevImage( evt:MouseEvent ):void {
			
			_imageIndex--;
			openImage( _arrImages[_imageIndex].url );
			
		}
		
		/**
		 * Active/Desactive Listeners.
		 *
		 * @param	status	Boolean
		 * @return			void
		 */
		private function activeListeners( status:Boolean ):void{
			
			var method:String = status ? 'addEventListener' : 'removeEventListener';
			
			//Close onClick Listener
			_close[method]( MouseEvent.CLICK, close );
			_close.buttonMode = status;			
			
			//Next onClick Listener
			_nextArrow[method]( MouseEvent.CLICK, nextImage );
			_nextArrow.buttonMode = status;
			
			//Prev onClick Listener
			_prevArrow[method]( MouseEvent.CLICK, prevImage );
			_prevArrow.buttonMode = status;
			
		}
		
		/**
		 * Resize Image to Fit.
		 *
		 * @return	void
		 */
		private function resizeImageToFit():void {
			
			var percentScale:Number = Math.min( stage.stageWidth / _originalImageW, stage.stageHeight / _originalImageH );
			
			TweenLite.to( _alvo, 0, { 
				
				width:Math.round( Math.min( _originalImageW, _originalImageW * percentScale - BORDER_SIZE*2 ) ),
				height:Math.round( Math.min( _originalImageH, _originalImageH * percentScale - BORDER_SIZE*2 ) )
				
			} );
			
		}
		
		/*-------------------------------------------------------------------------------------------------*\
		|* Handlers ---------------------------------------------------------------------------------------*|
		\*-------------------------------------------------------------------------------------------------*/
		
		/**
		 * Image Over Handler.
		 *
		 * @param	evt		MouseEvent
		 * @return			void
		 */
		private function imageOver( evt:MouseEvent = null ):void {
			
			if ( _activate ) {
				
				TweenMax.to( _alvo, .3, {
					
					colorMatrixFilter: {
						
						colorize:0x000000,
						amount:0.7
						
					},
					ease:Quint.easeOut
					
				} );
				
				TweenLite.to( _close, 		.3, { alpha:1 } );
				TweenLite.to( _prevArrow, 	.3, { alpha:1 } );
				TweenLite.to( _nextArrow,	.3, { alpha:1 } );
				
			}			
			
		}
		
		/**
		 * Image Out Handler.
		 *
		 * @param	evt		MouseEvent
		 * @return			void
		 */
		private function imageOut( evt:MouseEvent = null ):void {
			
			TweenMax.to( _alvo, .3, {
				
				colorMatrixFilter: { },
				ease:Quint.easeOut
				
			} );
			
			TweenLite.to( _close, 		.3, { alpha:0 } );
			TweenLite.to( _prevArrow, 	.3, { alpha:0 } );
			TweenLite.to( _nextArrow, 	.3, { alpha:0 } );
			
			_activate = true;
			
		}
		
		/**
		 * Close Handler.
		 *
		 * @param	evt		MouseEvent
		 * @return			void
		 */
		private function close( evt:MouseEvent = null ):void {
			
			activeListeners( false );
			
			animate( 'OUT' );
			
		}
		
		/**
		 * Item Complete Handler.
		 *
		 * @param	evt		QueueLoaderEvent
		 * @return			void
		 */
		private function itemComplete( evt:QueueLoaderEvent ):void {
			
			if( evt.filetype == QueueLoader.FILE_IMAGE ){
				
				evt.file.smoothing = true;
				
			}
			
		}
		
		/**
		 * Queue Complete Handler.
		 *
		 * @param	evt		QueueLoaderEvent
		 * @return			void
		 */
		private function queueComplete( evt:QueueLoaderEvent ):void {
			
			_originalImageW = _alvo.width;
			_originalImageH = _alvo.height;
			
			resizeImageToFit();
			
			_alvo.x = stage.stageWidth / 2 - _alvo.width / 2;
			_alvo.y = stage.stageHeight / 2 - _alvo.height / 2;
			
			TweenLite.to( _loading, .3, { 
				
				alpha:0
				
			} );
			
			imageOut();
			_activate = false;
			
			TweenLite.to( _bgAlvo, .5, { 
				
				ease:	Quint.easeOut,
				delay:	.5,
				width: 	_alvo.width + PADDING_SIZE,
				height:	_alvo.height + PADDING_SIZE,
				x:		_alvo.x - PADDING_SIZE / 2,
				y:		_alvo.y - PADDING_SIZE / 2
				
			} );
			
			TweenLite.to( _alvo, .5, { 
				
				ease:Quint.easeOut,
				delay:1,
				alpha:1,
				onComplete:function() {
					
					alignButtons();
					
					if ( _arrImages.length > 1 ) {
						
						_prevArrow.visible = _imageIndex > 0;
						_nextArrow.visible = _imageIndex < _arrImages.length - 1;						
						
					}
					
					activeListeners( true );
					
				}
				
			} );
			
		}
		
		/*-------------------------------------------------------------------------------------------------*\
		|* Getters e Setters ------------------------------------------------------------------------------*|
		\*-------------------------------------------------------------------------------------------------*/
				
		/**
		* DataProvider Setter.
		*
		* @param	arrImag	Array
		* @return			void
		*/
		public function set imageProvider( arrImag:Array ):void {
			
			if ( arrImag.length > 0 ) {
				
				_arrImages = arrImag;
				openImage( _arrImages[_imageIndex].url );
				
			}			
			
		}
		
		/**
		* Image Index Setter.
		*
		* @param	arrImag	Array
		* @return			void
		*/
		public function set imageIndex( intIndex:uint ):void {
			
			_imageIndex = intIndex;
			
		}
		
	}
	
}